
package main

import (
	"errors"
	"net"
	"time"
)

// stoppableListener在接受的
// 连接上设置TCP保持活动超时，并等待stopc消息
type stoppableListener struct {
	*net.TCPListener	//内嵌net.TCPListener
	// stopc通适用来监听是否应该关闭当前的Server，也就是raftNode中的httpstopc通道
	stopc <-chan struct{}
}

func newStoppableListener(addr string, stopc <-chan struct{}) (*stoppableListener, error) {
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}
	return &stoppableListener{ln.(*net.TCPListener), stopc}, nil
}

// stoppableListener.Accept（）方法重写了TCPListener.Accept（）方法
func (ln stoppableListener) Accept() (c net.Conn, err error) {
	connc := make(chan *net.TCPConn, 1)
	errc := make(chan error, 1)
	go func() {	// 启动羊独的goroutine来接收新连接
		tc, err := ln.AcceptTCP()
		if err != nil {
			errc <- err
			return
		}
		connc <- tc	// 将接收到新连接传递到connc通道中
	}()
	select {
	case <-ln.stopc:	// 从stopc迢迢中接收到通知时，会抛出异常
		return nil, errors.New("server stopped")
	case err := <-errc:	// 如果在接收新连接时出现异常，则抛出异常
		return nil, err
	case tc := <-connc:	// 接收到新建连接，设立KeepAlive等连接属性，并返回
		tc.SetKeepAlive(true)
		tc.SetKeepAlivePeriod(3 * time.Minute)
		return tc, nil
	}
}
